#include "cas.hpp"

namespace CAS{
    符号::~符号(){}
    shared_ptr<符号> 符号::operator+(shared_ptr<符号> 加数){
        return 加数?make_shared<加>(this,加数):make_shared<符号>(this);
    }
    shared_ptr<符号> 符号::operator-(shared_ptr<符号> 减数){
        return 减数?make_shared<减>(this,减数):make_shared<符号>(this);
    }
    shared_ptr<符号> 符号::operator*(shared_ptr<符号> 乘数){
        return 乘数?make_shared<乘>(this,乘数):make_shared<符号>(this);
    }
    shared_ptr<符号> 符号::operator/(shared_ptr<符号> 除数){
        return 除数?make_shared<除>(this,除数):make_shared<符号>(this);
    }

    二元符号::~二元符号(){}
    二元符号::二元符号(shared_ptr<符号> 左,shared_ptr<符号> 右):左(左),右(右){}

    int 常量::类型(){return 常量类型;}
    常量::常量(const string& 值):值(值){}
    常量::常量(const 实数& 值):值(值){}
    常量::~常量(){}
    shared_ptr<符号> 常量::代入(unordered_map<string,shared_ptr<符号>>& 参数){return make_shared<常量>(值);}
    shared_ptr<符号> 常量::求导(const string& 变量){return make_shared<常量>("0");}
    shared_ptr<符号> 常量::不定积分(const string& 变量){
        string s(变量+"_C");
        return make_shared<加>(make_shared<class 变量>(值,变量),make_shared<class 变量>(实数("1"),s));
    }
    shared_ptr<符号> 常量::定积分(const string& 变量,const 实数& 下界,const 实数& 上界){
        return make_shared<常量>((上界-下界)*值);
    }
    string 常量::文本(bool 小数形式,size_t 保留位数){
        if(小数形式)return 值.小数形式(保留位数);
        return 值.分数形式();
    }
    shared_ptr<符号> 常量::operator+(shared_ptr<符号> 加数){
        if(加数){
            if(加数->类型()==常量类型)return make_shared<常量>(值+((常量&)加数).值);
            return make_shared<加>(this,加数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 常量::operator-(shared_ptr<符号> 减数){
        if(减数){
            if(减数->类型()==常量类型)return make_shared<常量>(值-((常量&)减数).值);
            return make_shared<减>(this,减数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 常量::operator*(shared_ptr<符号> 乘数){
        if(乘数){
            if(乘数->类型()==常量类型)return make_shared<常量>(值*((常量&)乘数).值);
            return make_shared<乘>(this,乘数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 常量::operator/(shared_ptr<符号> 除数){
        if(除数){
            if(除数->类型()==常量类型)return make_shared<常量>(值/((常量&)除数).值);
            return make_shared<除>(this,除数);
        }
        return make_shared<符号>(this);
    }
    bool 常量::operator==(shared_ptr<符号> 符号2){
        auto p=static_pointer_cast<常量>(符号2);
        if(p->类型()==常量类型)return !值.比较(p->值);
        return false;
    }

    导数::导数(const string& 名称):名称(名称){}
    导数::~导数(){}
    string 导数::文本(bool 小数形式,size_t 保留位数){return "d"+名称;}
    shared_ptr<符号> 导数::代入(unordered_map<string,shared_ptr<符号>>& 参数){
        return make_shared<导数>(this);
    }
    shared_ptr<符号> 导数::求导(const string& 变量){
        return make_shared<导数>(this);
    }
    shared_ptr<符号> 导数::不定积分(const string& 变量){
        if(名称==变量)return make_shared<符号>(nullptr);
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 导数::定积分(const string& 变量,const 实数& 下界,const 实数& 上界){
        return make_shared<导数>(this);
    }
    bool 导数::operator==(shared_ptr<符号> 符号2){
        auto p=static_pointer_cast<导数>(符号2);
        if(p->类型()==导数类型)return 名称==p->名称;
        return false;
    }

    int 变量::类型(){return 变量类型;}
    变量::变量(const 实数& 系数,const string& 名称):系数(系数),名称(名称){}
    变量::~变量(){}
    shared_ptr<符号> 变量::代入(unordered_map<string,shared_ptr<符号>>& 参数){
        auto f=参数.find(名称);
        if(f!=参数.end()){
            return make_shared<常量>(系数)->operator*(f->second);
        }
        return make_shared<变量>(this);
    }
    shared_ptr<符号> 变量::求导(const string& 变量){
        if(名称==变量)return make_shared<常量>(系数);
        return make_shared<乘>(this,make_shared<导数>(变量));
    }
    shared_ptr<符号> 变量::不定积分(const string& 变量){
        
    }
    shared_ptr<符号> 变量::定积分(const string& 变量,const 实数& 下界,const 实数& 上界){
        

    }
    string 变量::文本(bool 小数形式,size_t 保留位数){
        if(小数形式)return 系数.小数形式(保留位数)+名称;
        return 系数.分数形式()+"*"+名称;
    }

    shared_ptr<符号> 变量::operator+(shared_ptr<符号> 加数){
        if(加数){
            if(加数->类型()==变量类型){
                auto p=static_pointer_cast<变量>(加数);
                if(名称==p->名称)return make_shared<变量>(系数+p->系数,名称);
            }
            return make_shared<加>(this,加数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 变量::operator-(shared_ptr<符号> 减数){
        if(减数){
            if(减数->类型()==变量类型){
                auto p=static_pointer_cast<变量>(减数);
                if(名称==p->名称)return make_shared<变量>(系数-p->系数,名称);
            }
            return make_shared<减>(this,减数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 变量::operator*(shared_ptr<符号> 乘数){
        if(乘数){
            if(乘数->类型()==变量类型){
                auto p=static_pointer_cast<变量>(乘数);
                auto c=make_shared<常量>(系数*p->系数);
                p->系数=实数("1");
                if(名称==p->名称)return make_shared<乘>(c,make_shared<指数>(p,make_shared<常量>("2")));
            }
            return make_shared<乘>(this,乘数);
        }
        return make_shared<符号>(this);
    }
    shared_ptr<符号> 变量::operator/(shared_ptr<符号> 除数){
        if(除数){
            if(除数->类型()==变量类型){
                auto p=static_pointer_cast<变量>(除数);
                if(名称==p->名称)return make_shared<常量>(系数/p->系数);
            }
            return make_shared<除>(this,除数);
        }
        return make_shared<符号>(this);
    }
    bool 变量::operator==(shared_ptr<符号> 符号2){
        auto p=static_pointer_cast<变量>(符号2);
        if(p->类型()==变量类型)return 名称==p->名称&&!系数.比较(p->系数);
        return false;
    }
}